{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [java 泛型详解](https://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845938.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 普通泛型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Point<T>{        // 此处可以随便写标识符号，T是type的简称\n",
    "    private T var;     // var的类型由T指定，即：由外部指定\n",
    "    public T getVar(){ // 返回值的类型由外部决定  \n",
    "        return var;\n",
    "    }\n",
    "    public void setVar(T var){  // 设置的类型也由外部决定\n",
    "        this.var = var;\n",
    "    }\n",
    "};\n",
    "\n",
    "Point<String> p = new Point<String>();  // 里面的var类型为String类型\n",
    "p.setVar(\"anlzou\");                     // 设置字符串\n",
    "System.out.print(p.getVar()+\" \");       // 获取字符串\n",
    "System.out.println(p.getVar().length());// 取得字符串的长度\n",
    "\n",
    "Point<Integer> p2 = new Point<Integer>();\n",
    "p2.setVar(24);\n",
    "System.out.println(p2.getVar());"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Book<N, V, P>{\n",
    "    private N name;\n",
    "    private V value;\n",
    "    private P price;\n",
    "    \n",
    "    public void setName(N name){\n",
    "        this.name = name;\n",
    "    }\n",
    "    \n",
    "    public void setValue(V value){\n",
    "        this.value = value;\n",
    "    }\n",
    "    \n",
    "    public void setPrice(P price){\n",
    "        this.price = price;\n",
    "    }\n",
    "    \n",
    "    public N getName(){\n",
    "        return this.name;\n",
    "    }\n",
    "    \n",
    "    public V getValue(){\n",
    "        return this.value;\n",
    "    }\n",
    "    \n",
    "    public P getPrice(){\n",
    "        return this.price = price;\n",
    "    }\n",
    "};\n",
    "\n",
    "Book<String, Integer, Double> book = new Book();\n",
    "book.setName(\"汤姆历险记\");\n",
    "book.setValue(99);\n",
    "book.setPrice(45.9);\n",
    "System.out.println(\"书名：\" + book.getName());\n",
    "System.out.println(\"数量：\" + book.getValue());\n",
    "System.out.println(\"价格：\" + book.getPrice());"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通配符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Info<T>{\n",
    "    private T var;  // 定义泛型变量  \n",
    "    public void setVar(T var){\n",
    "        this.var = var;\n",
    "    }\n",
    "    \n",
    "    public T getVar(){\n",
    "        return this.var;\n",
    "    }\n",
    "    \n",
    "    public String toString(){  // 调用该类对象默认输出，不存在则输出类地址\n",
    "        return this.var.toString();\n",
    "    }\n",
    "};\n",
    "\n",
    "public void printVar(Info<?> temp){  //等价于 ? extends Object\n",
    "    System.out.println(\"内容：\" + temp);\n",
    "};\n",
    "\n",
    "Info<Double> info = new Info();\n",
    "info.setVar(123.4);\n",
    "printVar(info);\n",
    "\n",
    "Info<String> info2 = new Info();\n",
    "info2.setVar(\"anlzou\");\n",
    "printVar(info2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 受限泛型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 上限：<? extends Class>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Info<T>{\n",
    "    private T var;\n",
    "    public void setVar(T var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public T getVar(){  \n",
    "        return this.var ;  \n",
    "    }  \n",
    "    public String toString(){   // 调用该类对象默认输出，不存在则输出类地址\n",
    "        return this.var.toString() ;  \n",
    "    }  \n",
    "};\n",
    "\n",
    "public void printNum(Info<? extends Number> temp){\n",
    "    System.out.println(temp);\n",
    "}\n",
    "\n",
    "Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象  \n",
    "Info<Float> i2 = new Info<Float>() ;            // 声明Float的泛型对象  \n",
    "i1.setVar(30) ;                                 // 设置整数，自动装箱  \n",
    "i2.setVar(30.1f) ;                              // 设置小数，自动装箱  \n",
    "\n",
    "printNum(i1);\n",
    "printNum(i2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 下限：<? super Class>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Info<T>{  \n",
    "    private T var ;            // 定义泛型变量  \n",
    "    public void setVar(T var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public T getVar(){  \n",
    "        return this.var ;  \n",
    "    }  \n",
    "    public String toString(){   // 调用该类对象默认输出，不存在则输出类地址\n",
    "        return this.var.toString() ;  \n",
    "    }  \n",
    "};  \n",
    "\n",
    "public void printObj(Info<? super String> temp){  // 只能接收String或Object类型的\n",
    "    System.out.println(temp);\n",
    "}\n",
    "\n",
    "Info<String> i1 = new Info<String>() ;            // 声明String的泛型对象  \n",
    "Info<Object> i2 = new Info<Object>() ;            // 声明Object的泛型对象 \n",
    "\n",
    "i1.setVar(\"hello\") ;  \n",
    "i2.setVar(new Object()) ;\n",
    "\n",
    "printObj(i1);\n",
    "printObj(i2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 泛型无法向上转型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Info<T>{  \n",
    "    private T var ;     // 定义泛型变量  \n",
    "    public void setVar(T var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public T getVar(){  \n",
    "        return this.var ;  \n",
    "    }  \n",
    "    public String toString(){   // 直接打印  \n",
    "        return this.var.toString() ;  \n",
    "    }  \n",
    "};  \n",
    "\n",
    "Info<String> i1 = new Info<String>() ;      // 泛型类型为String  \n",
    "Info<Object> i2 = null ;\n",
    "\n",
    "//这句会出错 incompatible types  \n",
    "//i2 = i1 ;  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 泛型接口"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interface Info<T>{      // 在接口上定义泛型  \n",
    "    public T getVar();  // 定义抽象方法，抽象方法的返回值就是泛型类型\n",
    "}\n",
    "\n",
    "class InfoImpl<T> implements Info<T>{  // 定义泛型接口的子类\n",
    "    private T var;                     // 定义属性  \n",
    "    \n",
    "    public InfoImpl(T var){            // 通过构造方法设置属性内容  \n",
    "        this.setVar(var);\n",
    "    }\n",
    "    \n",
    "    public void setVar(T var){\n",
    "        this.var = var;\n",
    "    }\n",
    "    \n",
    "    public T getVar(){\n",
    "        return this.var;\n",
    "    }\n",
    "};\n",
    "\n",
    "Info<Float> i = new InfoImpl(123.4f); // 通过子类实例化对象 \n",
    "System.out.println(\"内容：\" + i.getVar());"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interface Info<T>{        // 在接口上定义泛型  \n",
    "    public T getVar() ;   // 定义抽象方法，抽象方法的返回值就是泛型类型  \n",
    "}  \n",
    "class InfoImpl implements Info<String>{   // 定义泛型接口的子类  \n",
    "    private String var ;                  // 定义属性  \n",
    "    public InfoImpl(String var){          // 通过构造方法设置属性内容  \n",
    "        this.setVar(var) ;    \n",
    "    }  \n",
    "    public void setVar(String var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public String getVar(){  \n",
    "        return this.var ;  \n",
    "    }  \n",
    "};  \n",
    "\n",
    "Info i = new InfoImpl(\"汤姆\") ;    // 通过子类实例化对象  \n",
    "System.out.println(\"内容：\" + i.getVar()) ; "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 泛型方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Demo{\n",
    "    public <T> T fun(T t){    // 可以接收任意类型的数据 \n",
    "        return t;             // 直接把参数返回\n",
    "    }\n",
    "};\n",
    "\n",
    "Demo d = new Demo();          // 实例化Demo对象 \n",
    "String str = d.fun(\"anlzou\"); // 传递字符串 \n",
    "int i = d.fun(30);            // 传递数字，自动装箱  \n",
    "\n",
    "System.out.println(str);\n",
    "System.out.println(i);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 通过泛型方法返回泛型类型实例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Info<T extends Number>{ // 指定上限，只能是数字类型  \n",
    "    private T var ;     // 此类型由外部决定  \n",
    "    public T getVar(){  \n",
    "        return this.var ;     \n",
    "    }  \n",
    "    public void setVar(T var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public String toString(){       // 覆写Object类中的toString()方法  \n",
    "        return this.var.toString() ;      \n",
    "    }  \n",
    "};  \n",
    "\n",
    "/**\n",
    " * 方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定 \n",
    " */\n",
    "public <T extends Number> Info<T> fun(T param){\n",
    "    Info<T> temp = new Info();\n",
    "    temp.setVar(param);\n",
    "    return temp;\n",
    "}\n",
    "\n",
    "Info<Integer> i = fun(30);\n",
    "Info<Float> f = fun(24.5f);\n",
    "System.out.println(i.getVar());\n",
    "System.out.println(f.getVar());"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用泛型统一传入的参数类型(未完成)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Info<T>{           \n",
    "    private T var ;      // 此类型由外部决定  \n",
    "    public T getVar(){  \n",
    "        return this.var ;     \n",
    "    }  \n",
    "    public void setVar(T var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public String toString(){       // 覆写Object类中的toString()方法  \n",
    "        return this.var.toString() ;      \n",
    "    }  \n",
    "};  \n",
    "\n",
    "public <T> T add(Info<T> i1,Info<T> i2){  //todo:可以传入不同类型\n",
    "    System.out.println(i1.getVar() + \" \" + i2.getVar());\n",
    "    T t1 = i1.getVar();\n",
    "    T t2 = i2.getVar();\n",
    "    return t1;  //todo:返回两种类型相加\n",
    "}\n",
    "\n",
    "Info<Integer> i1 = new Info() ;  \n",
    "Info<Integer> i2 = new Info() ;  \n",
    "i1.setVar(34) ;        // 设置内容  \n",
    "i2.setVar(999) ;            // 设置内容  \n",
    "add(i1,i2) ;  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 泛型数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "public <T> T[] fun1(T...arg){\n",
    "    return arg;\n",
    "}\n",
    "\n",
    "public static <T> void fun2(T parm[]){\n",
    "    System.out.printf(\"接收范型数组：\");\n",
    "    for(T t:parm){\n",
    "     System.out.printf(t + \"、\");\n",
    "    }\n",
    "    System.out.println();\n",
    "}\n",
    "\n",
    "Integer i[] = fun1(1,2,3,4,5,6) ;   // 返回泛型数组  \n",
    "fun2(i); \n",
    "\n",
    "String a[] = fun1(\"1d\",\"2f\",\"3g\",\"4g\",\"5h\",\"6j\") ;   // 返回泛型数组  \n",
    "fun2(a); "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 泛型的嵌套设置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "内容一：汤姆\n",
      "内容二：30\n"
     ]
    }
   ],
   "source": [
    "class Info<T,V>{      // 接收两个泛型类型  \n",
    "    private T var ;  \n",
    "    private V value ;  \n",
    "    public Info(T var,V value){  \n",
    "        this.setVar(var) ;  \n",
    "        this.setValue(value) ;  \n",
    "    }  \n",
    "    public void setVar(T var){  \n",
    "        this.var = var ;  \n",
    "    }  \n",
    "    public void setValue(V value){  \n",
    "        this.value = value ;  \n",
    "    }  \n",
    "    public T getVar(){  \n",
    "        return this.var ;  \n",
    "    }  \n",
    "    public V getValue(){  \n",
    "        return this.value ;  \n",
    "    }  \n",
    "};  \n",
    "class Demo<S>{  \n",
    "    private S info ;  \n",
    "    public Demo(S info){  \n",
    "        this.setInfo(info) ;  \n",
    "    }  \n",
    "    public void setInfo(S info){  \n",
    "        this.info = info ;  \n",
    "    }  \n",
    "    public S getInfo(){  \n",
    "        return this.info ;  \n",
    "    }  \n",
    "};  \n",
    " \n",
    "\n",
    "Demo<Info<String,Integer>> d = null ;       // 将Info作为Demo的泛型类型  \n",
    "Info<String,Integer> i = null ;             // Info指定两个泛型类型  \n",
    "i = new Info<String,Integer>(\"汤姆\",30) ;   // 实例化Info对象  \n",
    "d = new Demo<Info<String,Integer>>(i) ;     // 在Demo类中设置Info类的对象  \n",
    "System.out.println(\"内容一：\" + d.getInfo().getVar()) ;  \n",
    "System.out.println(\"内容二：\" + d.getInfo().getValue()) ;  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ??? "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "public static <E> ArrayList<E> newArrayList() {\n",
    "    return new ArrayList<E>();\n",
    "}\n",
    "\n",
    "public static List<Number> queryHistories() {\n",
    "    return newArrayList();\n",
    "}\n",
    "\n",
    "newArrayList();\n",
    "queryHistories();"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Java",
   "language": "java",
   "name": "java"
  },
  "language_info": {
   "codemirror_mode": "java",
   "file_extension": ".jshell",
   "mimetype": "text/x-java-source",
   "name": "Java",
   "pygments_lexer": "java",
   "version": "11.0.8+10-post-Ubuntu-0ubuntu120.04"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "249.95px"
   },
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
